﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace CoffeePotServer
{
    public class HTCPCPServer
    {
        #region Attributes
        private static List<Pot> _pots;
        private static List<Client_Handler> _clients;
        private static Socket _sktServer;
        private static Boolean _bolDebug;
        #endregion

        #region Constructor
        /// <summary>
        /// An HTCPCP Server.
        /// </summary>
        /// <param name="port">Port to listen on.</param>
        public HTCPCPServer(int port)
        {
            _pots = new List<Pot>();
            _clients = new List<Client_Handler>();
            _sktServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _sktServer.Bind(new IPEndPoint(IPAddress.Any, port));
            _sktServer.Listen(5);
        }
        #endregion

        #region Properties
        /// <summary>
        /// The pots controlled by the Server.
        /// </summary>
        public static List<Pot> Pots
        {
            get { return _pots; }
        }

        /// <summary>
        /// Clients connected to the server.
        /// </summary>
        public static List<Client_Handler> Clients
        {
            get{ return _clients; }
        }

        /// <summary>
        /// Whether verbose output is on.
        /// </summary>
        public static Boolean DebugMode
        {
            get{ return _bolDebug; }
            set { _bolDebug = value; }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Start accepting clients.
        /// </summary>
        public void StartListening()
        {
            _sktServer.BeginAccept(new AsyncCallback(ClientConnected), null);
        }

        /// <summary>
        /// Handle a newly connected client.
        /// </summary>
        /// <param name="arClient"></param>
        private void ClientConnected(IAsyncResult arClient)
        {
            Client_Handler clNewClient = new Client_Handler(_sktServer.EndAccept(arClient));
            _clients.Add(clNewClient);
            new Thread(clNewClient.HandleClient).Start();
            _sktServer.BeginAccept(new AsyncCallback(ClientConnected), null);
            Console.WriteLine("[{0}] {1} Connected",
                              DateTime.Now.ToLongTimeString(),
                              clNewClient.Hostname);
        }

        public void StopListening()
        {
            _sktServer.Close();
        }

        /// <summary>
        /// Create a new pot to use on the server.
        /// </summary>
        public void AddNewPot()
        {
            _pots.Add(new Pot(_pots.Count + 1));
        }
        #endregion
    }
}
